package cn.iocoder.yudao.module.product.service.calculation;

import cn.iocoder.yudao.module.product.controller.admin.calculationmodel.vo.ProcessModelRespVO;
import cn.iocoder.yudao.module.product.controller.admin.emissionsource.vo.EmissionSourceEPCRespVO;
import cn.iocoder.yudao.module.product.controller.admin.emissionsource.vo.EmissionSourceEPRespVO;
import cn.iocoder.yudao.module.product.controller.admin.process.vo.EmissionProcessResp1VO;
import cn.iocoder.yudao.module.product.controller.admin.process.vo.EmissionProcessResp2VO;
import cn.iocoder.yudao.module.product.controller.admin.process.vo.ProcessPMDetailsResVO;
import cn.iocoder.yudao.module.product.convert.emissionsource.EmissionSourceConvert;
import cn.iocoder.yudao.module.product.convert.process.ProcessConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.calculation.EmissionCalculationDO;
import cn.iocoder.yudao.module.product.dal.dataobject.calculation.ProcessCalculationDO;
import cn.iocoder.yudao.module.product.dal.dataobject.emissionsource.EmissionSourceDO;
import cn.iocoder.yudao.module.product.dal.mysql.calculation.EmissionCalculationMapper;
import cn.iocoder.yudao.module.product.dal.mysql.calculation.ProcessCalculationMapper;
import cn.iocoder.yudao.module.product.dal.mysql.emissionsource.EmissionSourceMapper;
import cn.iocoder.yudao.module.product.service.calculationmodel.ProcessModelService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import cn.iocoder.yudao.module.product.controller.admin.calculation.vo.*;
import cn.iocoder.yudao.module.product.dal.dataobject.calculation.CalculationDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.product.convert.calculation.CalculationConvert;
import cn.iocoder.yudao.module.product.dal.mysql.calculation.CalculationMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;

/**
 * 产品碳核算 Service 实现类
 *
 * @author wcl
 */
@Service
@Validated
public class CalculationServiceImpl implements CalculationService {

    @Resource
    private CalculationMapper calculationMapper;

    @Resource
    private EmissionCalculationMapper emissionCalculationMapper;

    @Resource
    private EmissionSourceMapper emissionSourceMapper;

    @Resource
    private ProcessModelService processModelService;

    @Resource
    private ProcessCalculationMapper processCalculationMapper;

    @Override
    public Long createCalculation(CalculationCreateReqVO createReqVO) {
        // 插入
        CalculationDO calculation = CalculationConvert.INSTANCE.convert(createReqVO);
        calculationMapper.insert(calculation);
        // 返回
        return calculation.getId();
    }

    @Override
    public void updateCalculation(CalculationUpdateReqVO updateReqVO) {
        // 校验存在
        validateCalculationExists(updateReqVO.getId());
        // 更新
        CalculationDO updateObj = CalculationConvert.INSTANCE.convert(updateReqVO);
        calculationMapper.updateById(updateObj);
    }

    @Override
    public void deleteCalculation(Long id) {
        // 校验存在
        validateCalculationExists(id);
        // 删除
        calculationMapper.deleteById(id);
    }

    private void validateCalculationExists(Long id) {
        if (calculationMapper.selectById(id) == null) {
            throw exception(CALCULATION_NOT_EXISTS);
        }
    }

    @Override
    public CalculationDO getCalculation(Long id) {
        return calculationMapper.selectById(id);
    }

    @Override
    public List<CalculationDO> getCalculationList(Collection<Long> ids) {
        return calculationMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<CalculationDO> getCalculationPage(CalculationPageReqVO pageReqVO) {
        return calculationMapper.selectPage(pageReqVO);
    }

    @Override
    public CalculationDetailsRespVO getCalculationDetails(Long id) {
        List<EmissionProcessResp2VO> lists = new ArrayList<>();
        List<EmissionSourceEPCRespVO> list = new ArrayList<>();
        // 获取核算信息
        CalculationDO calculationDO = calculationMapper.selectById(id);
        // 先获得模型的所有详细数据
        ProcessModelRespVO processModelRespVO = processModelService.getProcessModel(calculationDO.getCalculationModelId());
        // 修改排放源信息和工序信息
        for (EmissionProcessResp1VO item0 : processModelRespVO.getLists()) {
            // 工序中增加工序-核算关联表id、核算数量和核算单位
            ProcessPMDetailsResVO processPMDetailsResVO = ProcessConvert.INSTANCE.convert(item0.getProcessPMResVO());
            QueryWrapper<ProcessCalculationDO> queryWrapper0 = new QueryWrapper<>();
            queryWrapper0.eq("process_id", processPMDetailsResVO.getId())
                         .eq("calculation_id", id);
            System.out.println(processPMDetailsResVO.getPeriodName()+"=================");
            ProcessCalculationDO processCalculationDO = processCalculationMapper.selectOne(queryWrapper0);
            processPMDetailsResVO.setNum(processCalculationDO != null ? processCalculationDO.getNum() : null);
            processPMDetailsResVO.setUnit(processCalculationDO != null ? processCalculationDO.getUnit() : null);
            // 排放源中增加排放源-工序-核算关联表id、核算数量和核算单位
            for (EmissionSourceEPRespVO item1 : item0.getEmissions()) {
                QueryWrapper<EmissionCalculationDO> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("emission_id", item1.getId())
                        .eq("process_id", processPMDetailsResVO.getId())
                        .eq("calculation_id", id);
                EmissionCalculationDO emissionCalculationDO = emissionCalculationMapper.selectOne(queryWrapper1);
                EmissionSourceEPCRespVO emissionSourceEPCRespVO = EmissionSourceConvert.INSTANCE.convertEPC(item1);
                emissionSourceEPCRespVO.setCalId(id);
                emissionSourceEPCRespVO.setNum(emissionCalculationDO != null ? emissionCalculationDO.getNum() : null);
                emissionSourceEPCRespVO.setUnit(emissionCalculationDO != null ? emissionCalculationDO.getUnit() : null);
                list.add(emissionSourceEPCRespVO);
            }
            EmissionProcessResp2VO emissionProcessResp2VO = new EmissionProcessResp2VO();
            emissionProcessResp2VO.setProcessPMResVO(processPMDetailsResVO);
            lists.add(emissionProcessResp2VO);
            emissionProcessResp2VO.setEmissions(list);
            list = new ArrayList<>();
        }
        CalculationDetailsRespVO calculationDetailsRespVO = new CalculationDetailsRespVO();
        calculationDetailsRespVO.setCalculationDO(calculationDO);
        calculationDetailsRespVO.setCalculationModelDO(processModelRespVO.getCalculationModelDO());
        calculationDetailsRespVO.setProductManagementDO(processModelRespVO.getProductManagementDO());
        calculationDetailsRespVO.setLists(lists);
        return calculationDetailsRespVO;
    }

    @Override
    public Double countCalculation(Long id) {
        Double sum = 0.0;
        QueryWrapper<EmissionCalculationDO> queryWrapper0 = new QueryWrapper<>();
        queryWrapper0.eq("calculation_id", id);
        QueryWrapper<EmissionSourceDO> queryWrapper1 = new QueryWrapper<>();
        List<EmissionCalculationDO> emissionCalculationDOList = emissionCalculationMapper.selectList(queryWrapper0);
        for (EmissionCalculationDO item : emissionCalculationDOList) {
            queryWrapper1.eq("id", item.getEmissionId());
            EmissionSourceDO emissionSourceDO = emissionSourceMapper.selectOne(queryWrapper1);
            sum += emissionSourceDO.getFactorEmissions() * item.getNum();
        }
        return sum;
    }

}
